package com.lib.common.view;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.graphics.drawable.AnimationDrawable;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageView;

import com.lib.common.R;
import com.lib.utils.XLog;

public class BezierView extends FrameLayout {
    // 默认定点圆半径
    public static final float DEFAULT_RADIUS = 20;

    private Paint mPaint = new Paint();
    private Path mPath = new Path();
    // 拖动时手势坐标
    private float mX;
    private float mY;
    // 锚点坐标
    private float mAnchorX;
    private float mAnchorY;
    // 起点坐标
    private float mStartX;
    private float mStartY;
    // 定点圆半径
    private float mDefaultRadius = DEFAULT_RADIUS;
    // 判断动画是否开始
    private boolean mHaveReleased;
    // 判断是否开始拖动
    private boolean mIsDragging;
    //释放之后的动画
    private ImageView mReleaseView;
    private View mView;
    //默认释放的消失动画居中
    private boolean mReleaseAnimCenter = false;
    private OnDraggingReleaseListener mOnDraggingReleaseListener;

    public interface OnDraggingReleaseListener {

        void OnDraggingReleased(View view);
    }

    public void setOnDraggingReleaseListener(OnDraggingReleaseListener l) {

        mOnDraggingReleaseListener = l;
    }

    public BezierView(Context context) {

        this(context, null);
    }

    public BezierView(Context context, AttributeSet attrs) {

        this(context, attrs, 0);
    }

    public BezierView(Context context, AttributeSet attrs, int defStyle) {

        super(context, attrs, defStyle);

        setBackgroundColor(Color.TRANSPARENT);
        mPaint.setAntiAlias(true);
        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setColor(Color.RED);

        LayoutParams params = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        if (mReleaseAnimCenter) {
            params.gravity = Gravity.CENTER;
        }
        mReleaseView = new ImageView(context);
        mReleaseView.setImageResource(R.drawable.release_anim);
        mReleaseView.setVisibility(View.GONE);
        addView(mReleaseView, -1, params);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        mView = getChildAt(1);
        mStartX = mAnchorX = getMeasuredWidth() / 2;
        mStartY = mAnchorY = getMeasuredHeight() / 2;
    }

    private void calculate() {

        float distance = (float) Math.sqrt(Math.pow(mY - mStartY, 2) + Math.pow(mX - mStartX, 2));
        mDefaultRadius = -distance / 15 + DEFAULT_RADIUS;

        if (mDefaultRadius < 9) {
            mReleaseView.setVisibility(View.VISIBLE);
            ((AnimationDrawable) mReleaseView.getDrawable()).stop();
            ((AnimationDrawable) mReleaseView.getDrawable()).start();
            if (mView != null) {
                mView.setVisibility(View.GONE);
            }
            if (mOnDraggingReleaseListener != null) {
                mOnDraggingReleaseListener.OnDraggingReleased(this);
            }
            mHaveReleased = true;
        }

        // 根据角度算出四边形的四个点
        float offsetX = (float) (mDefaultRadius * Math.sin(Math.atan((mY - mStartY) / (mX - mStartX))));
        float offsetY = (float) (mDefaultRadius * Math.cos(Math.atan((mY - mStartY) / (mX - mStartX))));

        float x1 = mStartX - offsetX;
        float y1 = mStartY + offsetY;

        float x2 = mX - offsetX;
        float y2 = mY + offsetY;

        float x3 = mX + offsetX;
        float y3 = mY - offsetY;

        float x4 = mStartX + offsetX;
        float y4 = mStartY - offsetY;

        mPath.reset();
        mPath.moveTo(x1, y1);
        mPath.quadTo(mAnchorX, mAnchorY, x2, y2);
        mPath.lineTo(x3, y3);
        mPath.quadTo(mAnchorX, mAnchorY, x4, y4);
        mPath.lineTo(x1, y1);

        // 更改图标的位置
        int width = mView.getWidth();
        int height = mView.getHeight();
        if (mView != null) {
            mView.setX(mX - width / 2);
            mView.setY(mY - height / 2);
        }
        if (!mReleaseAnimCenter) {
            //释放动画的位置跟随主动画
            mReleaseView.setX(mX - width / 2);
            mReleaseView.setY(mY - height / 2);
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {

        if (mHaveReleased || !mIsDragging) {
            canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.OVERLAY);
        } else {
            calculate();
            canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.OVERLAY);
            canvas.drawPath(mPath, mPaint);
            canvas.drawCircle(mStartX, mStartY, mDefaultRadius, mPaint);
            canvas.drawCircle(mX, mY, mDefaultRadius, mPaint);
        }
        super.onDraw(canvas);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {

        if (mHaveReleased) {
            return super.onTouchEvent(event);
        }
        int action = event.getAction();
        switch (action) {
            case MotionEvent.ACTION_DOWN:
                Rect rect = new Rect();
                int[] location = new int[2];
                if (mView != null) {
                    mView.getDrawingRect(rect);
                    mView.getLocationOnScreen(location);
                }
                rect.left = location[0];
                rect.top = location[1];
                rect.right = rect.right + location[0];
                rect.bottom = rect.bottom + location[1];
                if (rect.contains((int) event.getRawX(), (int) event.getRawY())) {
                    mIsDragging = true;
                }
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                XLog.i("onTouchEvent: ");
                mIsDragging = false;
                if (mView != null) {
                    mView.setX(mStartX - mView.getWidth() / 2);
                    mView.setY(mStartY - mView.getHeight() / 2);
                }
                break;
        }
        invalidate();
        mX = event.getX();
        mY = event.getY();
        return true;
    }
}
